package com.iot.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Service
public class DataDockingService implements InitializingBean {
	private static final Logger logger = LoggerFactory.getLogger(DataDockingService.class);

	@Value("${maijie.appId}")
	private String appId;
	@Value("${maijie.secretKey}")
	private String secretKey;
	@Value("${maijie.url}")
	private String url;

	@Autowired
	private ObjectMapper objectMapper;
	@Autowired
	private RestTemplate restTemplate;
	@Autowired
    private RocketMQTemplate rocketMQTemplate;

	private String token;
	private Long tokenDueTime;// token有效时间戳

	@Override
	public void afterPropertiesSet() throws Exception {
		this.authorization();
	}

	public void authorization() throws JsonMappingException, JsonProcessingException {
		logger.info("获取AccessToken开始******");
		
		String tokenUrl = url + "/mj10/mjdtface/getAccessToken";
		logger.info("获取AccessToken参数appId={},secretKey={},url={}", appId, secretKey, tokenUrl);

		HttpHeaders headers = new HttpHeaders();

		MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<>();
		paramMap.add("AppId", appId);
		paramMap.add("SecretKey", secretKey);

		HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(paramMap, headers);

		String result = restTemplate.postForObject(tokenUrl, request, String.class);
		logger.info("获取AccessToken结果={}", result);
		
		Map<String, Object> resultMap = objectMapper.readValue(result, Map.class);
		Map<String, Object> dataMap = (Map<String, Object>) resultMap.get("data");
		token = String.valueOf(dataMap.get("AccessToken"));
		tokenDueTime = Long.valueOf(String.valueOf(dataMap.get("DueTime")));
		logger.info("token={}", token);

		logger.info("获取AccessToken结束******");
	}
	
	public void getRealData() throws JsonMappingException, JsonProcessingException {
		// 判断token是否过期
		Long now = System.currentTimeMillis();
		if(now.longValue() > tokenDueTime.longValue()) {
			logger.info("token过期，now={}，dueTime={}，重新获取token", now, tokenDueTime);
			this.authorization();
		} else {
			logger.info("token有效，now={}，dueTime={}", now, tokenDueTime);
		}
		
		logger.info("获取实时数据开始******");
		
		String realDataUrl = url + "/mj10/mjdtface/getRealData";
		logger.info("实时数据接口地址={}", realDataUrl);
		
		HttpHeaders headers = new HttpHeaders();
		headers.add("Authorization", token);
		
		HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(new LinkedMultiValueMap<>(), headers);
		
		String result = restTemplate.postForObject(realDataUrl, request, String.class);
		logger.info("实时数据接口结果={}", result);
		
		Map<String, Object> resultMap = objectMapper.readValue(result, Map.class);
		Map<String, Object> dataMap = (Map<String, Object>) resultMap.get("data");
		Map<String, Object> mqDataMap = null;
		List<Map<String, Object>> mqDataList = null;
		List<Map<String, Object>> configs = (List<Map<String, Object>>) dataMap.get("configs");
		for(Map<String, Object> configMap : configs) {
			List<Map<String, Object>> configDatas = (List<Map<String, Object>>) configMap.get("configDatas");
			
			for(Map<String, Object> configDataMap : configDatas) {
				//String stId = String.valueOf(configDataMap.get("stId"));
				String rtuId = String.valueOf(configDataMap.get("rtuId"));
				String msg = objectMapper.writeValueAsString(configDataMap);
				logger.info("{}={},", rtuId, msg);
				
				// 根据格式组装数据
				mqDataList = new ArrayList<>();
				
				for(Map.Entry<String, Object> entry : configDataMap.entrySet()) {
					String entryKey = entry.getKey();
					// 排除常规固定字段，剩下的就是点位字段
					if(StringUtils.equalsIgnoreCase("stId", entryKey)) {
						continue;
					}
					if(StringUtils.equalsIgnoreCase("stName", entryKey)) {
						continue;
					}
					if(StringUtils.equalsIgnoreCase("rtuId", entryKey)) {
						continue;
					}
					if(StringUtils.equalsIgnoreCase("deviceId", entryKey)) {
						continue;
					}
					if(StringUtils.equalsIgnoreCase("ols", entryKey)) {
						continue;
					}
					if(StringUtils.equalsIgnoreCase("dataTime", entryKey)) {
						continue;
					}
					mqDataMap = new HashMap<>();
					mqDataMap.put("key", entryKey);
					mqDataMap.put("id", entryKey);
					mqDataMap.put("val", entry.getValue());
					mqDataList.add(mqDataMap);
				}
				
				Map<String, Object> mqMap = new HashMap<>();
				mqMap.put("devId", rtuId);
				mqMap.put("sn", rtuId);
				mqMap.put("time", configDataMap.get("dataTime"));
				mqMap.put("tenantId", null);
				mqMap.put("tags", null);
				mqMap.put("data", mqDataList);
				
				String mq = objectMapper.writeValueAsString(mqMap);
				rocketMQTemplate.asyncSend("iot-lushan", MessageBuilder.withPayload(mq).setHeader("KEYS", rtuId).build(), new SendCallback() {
					@Override
				    public void onSuccess(SendResult result) {
				        if (result.getSendStatus() == SendStatus.SEND_OK) {
				        	logger.info("数据发送成功={}", mq);
				        }
				    }
				    @Override
				    public void onException(Throwable e) {
				    	logger.error("数据发送失败={}", e.getMessage());
				    }
				});
			}
		}
		
		logger.info("获取实时数据结束******");
	}
	
	public List<Map<String, Object>> getDevInfo() throws JsonProcessingException {
		// 判断token是否过期
		Long now = System.currentTimeMillis();
		if(now.longValue() > tokenDueTime.longValue()) {
			logger.info("token过期，now={}，dueTime={}，重新获取token", now, tokenDueTime);
			this.authorization();
		} else {
			logger.info("token有效，now={}，dueTime={}", now, tokenDueTime);
		}
		
		logger.info("获取设备信息开始******");
		
		String realDataUrl = url + "/mj10/mjdtface/getRealData";
		logger.info("实时数据接口地址={}", realDataUrl);
		
		HttpHeaders headers = new HttpHeaders();
		headers.add("Authorization", token);
		
		HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(new LinkedMultiValueMap<>(), headers);
		
		String result = restTemplate.postForObject(realDataUrl, request, String.class);
		logger.info("实时数据接口结果={}", result);
		
		Map<String, Object> resultMap = objectMapper.readValue(result, Map.class);
		Map<String, Object> dataMap = (Map<String, Object>) resultMap.get("data");
		
		List<Map<String, Object>> devList = Lists.newArrayList();// 设备列表
		List<Map<String, Object>> configs = (List<Map<String, Object>>) dataMap.get("configs");
		for(Map<String, Object> configMap : configs) {
			// 获取点位配置，组装点位配置
			List<Map<String, Object>> devDataList = Lists.newArrayList();
			for(Map.Entry<String, Object> entry : configMap.entrySet()) {
				String entryKey = entry.getKey();
				// 排除常规固定字段，剩下的就是点位字段
				if(StringUtils.equalsIgnoreCase("configId", entryKey)) {
					continue;
				}
				if(StringUtils.equalsIgnoreCase("configName", entryKey)) {
					continue;
				}
				if(StringUtils.equalsIgnoreCase("configDataCount", entryKey)) {
					continue;
				}
				if(StringUtils.equalsIgnoreCase("configDatas", entryKey)) {
					continue;
				}
				
				Map<String, Object> devDataMap = Maps.newHashMap();
				devDataMap.put("key", entryKey);
				devDataMap.put("name", entry.getValue());
				
				devDataList.add(devDataMap);
			}
			
			// 组装设备配置、点位
			List<Map<String, Object>> configDatas = (List<Map<String, Object>>) configMap.get("configDatas");
			for(Map<String, Object> configDataMap : configDatas) {
				Map<String, Object> devMap = Maps.newHashMap();
				devMap.put("devId", configDataMap.get("rtuId"));
				devMap.put("devName", configDataMap.get("stName"));
				devMap.put("sn", configDataMap.get("rtuId"));
				devMap.put("data", devDataList);
				devList.add(devMap);
			}
		}
		
		logger.info("设备信息={}", objectMapper.writeValueAsString(devList));
		logger.info("获取设备信息结束******");
		
		return devList;
	}
}